#pragma once
#include<iostream>
#include<string>
#include<unordered_map>
#include"../comm/util.hpp"
#include"../comm/log.hpp"
#include<cassert>
#include<vector>
#include<fstream>
#include<cstdlib>

//加载题库
namespace ns_model
{using namespace std;
using namespace ns_log;
using namespace ns_util;
    struct Question
    {
        std::string num;//题号
        std::string title;//标题
        std::string star;//难度
        int cpu_limit;//时间要求
        int mem_limit;//空间要求
        std::string desc;//描述
        std::string header;//用户在线代码
        std::string tail;//和header拼接cheng完整代码
    };
    const std::string question_list="./question/question.list";
    const std::string question_path="./question/";
    class Model
    {
        private:
        unordered_map<string,Question> questions;
        public:
        Model()
        {
          assert(LoadQuestionList(question_list));
        }
        bool LoadQuestionList(const std::string &question_list)
        {
           //question_list+题目配置文件
           ifstream in(question_list.c_str());
           if(!in.is_open())
           {
            LOG(FATAL)<<"加载题库失败,请检查题库文件"<<"\n";
            return false;
           }
           std::string line;
           while(getline(in,line))
           {
            vector<string> tokens;
               StringUtil::SplitString(line,&tokens," ");
               if(tokens.size()!=5)
               {
                LOG(WARNING)<<"加载部分题目失败,注意文件格式"<<"\n";
                continue;
               }
               Question q;
               q.num=tokens[0];
               q.title=tokens[1];
               q.star=tokens[2];
               q.cpu_limit=atoi(tokens[3].c_str());
               q.mem_limit=atoi(tokens[4].c_str());
              string path=question_path;
              path+=q.num;
              path+="/";

              
              FileUtil::ReadFile(path+"desc.txt",&(q.desc),true);
              FileUtil::ReadFile(path+"header.cpp",&(q.header),true);
              FileUtil::ReadFile(path+"tail.cpp",&(q.tail),true);

              questions.insert({q.num, q});

           }
           LOG(INFO)<<"加载题库成功!"<<"\n";
           in.close();
           return true;

        }
        bool GetAllQuestions(vector<Question> *out)
        {
              if(questions.size()==0)
              {
                LOG(ERROR)<<"用户获取题库失败"<<"\n";
                return false;
              }
              for(const auto &q:questions)
              {
                out->push_back(q.second);
              }
              return true;
        }
        bool GetOneQuestion(const std::string &number,Question *q)
        {
         const auto &iter=questions.find(number);
         if(iter==questions.end())
         {
          LOG(ERROR)<<"用户获取题目失败,编号:"<<number<<"\n";
            return false;
         }
         (*q)=iter->second;
         return true;
        }
        ~Model()
        {}
    };
}